<?php

namespace services\rbac;

use api\modules\v1\forms\rbac\ActionForm;
use common\components\Service;
use common\helpers\CommonHelper;
use common\models\member\Member;
use common\models\rbac\Action;
use common\models\rbac\Menu;
use common\models\rbac\Module;
use common\models\rbac\Role;
use common\models\rbac\RolePermission;
use common\models\rbac\UserRole;

/**
 * Class ActionService
 * @package services\rbac
 */
class ActionService extends Service
{
    /**
     * 根据ID查找动作信息
     *
     * @param int $id
     * @return Action|null
     */
    public function findById(int $id = 0): ?Action
    {
        return Action::find()->where(['id' => $id])->one();
    }

    /**
     * 获取信息
     *
     * @param array $condition
     * @return array|\yii\db\ActiveRecord|null
     */
    public function findInfo(array $condition = [])
    {
        $query = Action::find();

        isset($condition['menu_id']) && $query->andWhere(['menu_id' => $condition['menu_id']]);
        isset($condition['name']) && $query->andWhere(['name' => $condition['name']]);
        isset($condition['flag']) && $query->andWhere(['flag' => $condition['flag']]);
        isset($condition['status']) && $query->andWhere(['status' => $condition['status']]);

        return $query->asArray()->one();
    }


    /**
     * 获取列表
     *
     * @param array $condition
     * @return array|\yii\db\ActiveRecord[]
     */
    public function findList(array $condition = [])
    {
        $query = Action::find();

        isset($condition['id']) && $query->andWhere(['id' => $condition['id']]);
        isset($condition['status']) && $query->andWhere(['status' => $condition['status']]);

        return $query->asArray()->all();
    }

    /**
     * 动作列表
     *
     * @param array $params
     * @param int $page
     * @param int $pageSize
     * @return array
     */
    public function getListPage(array $params = [], int $page = 0, int $pageSize = 0)
    {
        $query = Action::find()->alias('a')
            ->select([
                'a.*',
                'b.name as module_name',
                'c.name as menu_name',
            ])
            ->leftJoin(Module::tableName(). ' AS b', 'a.module_id = b.id')
            ->leftJoin(Menu::tableName(). ' AS c', 'a.menu_id = c.id')
            ->where(['a.status' => [Action::STATUS_INVALID, Action::STATUS_ENABLE]]);

        // 总数
        $total = $query->count();

        // 分页
        if ($page && $pageSize) {
            $query->limit($pageSize)->offset(($page - 1) * $pageSize);
        }

        $list = $query
            ->orderBy(['a.sort' => SORT_ASC, 'a.id' => SORT_DESC])
            ->asArray()
            ->all();

        return [
            'page' => (int)$page,
            'pageSize' => (int)$pageSize,
            'total' => (int)$total,
            'list' => $list,
        ];
    }

    /**
     * 格式化动作列表
     *
     * @param array $data
     * @return array
     */
    public function getListPageFormat(array $data = [])
    {
        $list = [];
        foreach ($data as $row) {
            $list[] = [
                'id' => $row['id'],
                'menu_id' => $row['menu_id'],
                'module_id' => $row['module_id'],
                'name' => $row['name'],
                'menu_name' => $row['menu_name'] ? $row['menu_name'] : '',
                'module_name' => $row['module_name'] ? $row['module_name'] : '',
                'flag' => $row['flag'],
                'sort' => $row['sort'],
                'status' => $row['status'],
                'status_str' => Action::$statuss[$row['status']],
                'created_at_str' => $row['created_at'] ? date('Y-m-d H:i:s', $row['created_at']) : '',
            ];
        }

        return $list;
    }

    /**
     * 新增动作
     *
     * @param ActionForm $model
     * @return array|mixed
     */
    public function create(ActionForm $model)
    {
        try {
            // 1.新增动作
            $action = new Action();
            $action->module_id = $model->module_id;
            $action->menu_id = $model->menu_id;
            $action->name = $model->name;
            $action->flag = $model->flag;
            $action->status = $model->status;
            $action->sort = $model->sort;
            $action->saveAndCheckResult();

            return ['id' => $action->id];
        } catch (\Exception $e) {
            return CommonHelper::api(422, $e->getMessage());
        }
    }

    /**
     * 编辑动作
     *
     * @param ActionForm $model
     * @return array|mixed
     */
    public function edit(ActionForm $model)
    {
        try {
            // 1.更新动作
            $attributes = [
                'menu_id' => $model->menu_id,
                'name' => $model->name,
                'flag' => $model->flag,
                'status' => $model->status,
                'sort' => $model->sort,
            ];
            Action::updateAll($attributes, ['id' => $model->id]);

            return ['id' => $model->id];
        } catch (\Exception $e) {
            return CommonHelper::api(422, $e->getMessage());
        }
    }

    /**
     * 删除动作
     *
     * @param ActionForm $model
     * @return array|mixed
     */
    public function delete(ActionForm $model)
    {
        try {
            // 1.更新动作
            $attributes = [
                'status' => Action::STATUS_DELETE,
            ];
            Action::updateAll($attributes, ['id' => $model->id]);

            return ['id' => $model->id];
        } catch (\Exception $e) {
            return CommonHelper::api(422, $e->getMessage());
        }
    }

    /**
     * 是否存在该权限
     * @param int $projectId
     * @param string $flag
     * @return bool
     */
    public function isHaveLimit(int $projectId, string $flag): bool
    {
        $member = Member::findOne(\Yii::$app->user->identity->member_id);
        if ($member && $member->is_super == Member::IS_SUPER_YES) {
            return true;
        }

        $hasLimit = UserRole::find()->alias('ur')
            ->select(['ur.role_id'])
            ->innerJoin(Role::tableName().' r', 'r.id = ur.role_id')
            ->innerJoin(RolePermission::tableName().' rp', 'rp.role_id = ur.role_id')
            ->innerJoin(Action::tableName().' a', 'a.id = rp.permission_id')
            ->where([
                'ur.project_id' => $projectId,
                'ur.member_id' => \Yii::$app->user->identity->member_id,
                'r.status' => Role::STATUS_ENABLE,
                'rp.permission_type' => RolePermission::PERMISSION_TYPE_ACTION,
                'a.status' => Action::STATUS_ENABLE,
                'a.flag' => $flag,
            ])
            ->one();
        
        return $hasLimit ? true : false;
    }
}
